package gnss

import (
	"dgo/goutils/utils"
)

/*
*
 */
type GnssYObs struct {
	NaviSys byte
	Satid   byte // 卫星号
	RoughR  float64
	PsRngV  [32]float64 // 最终的伪距  单位:米
	//PsRngV  map[byte]float64
	PhRngV  [32]float64 // 最终的相位  单位:周
	Doppler [32]float64
	LkT     [32]int64 // 锁定时间, 单位ms
	HalfAmb [32]byte
	Cnr     [32]float32
	LLI     [32]byte
}

func (this *GnssYObs) GetPrnCode() string {
	return GetPrnStrCode(this.Satid, this.NaviSys)
}

func (this *GnssYObs) CopySig(src, dst byte) {
	this.PhRngV[dst-1] = this.PhRngV[src-1]
	this.PsRngV[dst-1] = this.PsRngV[src-1]
	this.Doppler[dst-1] = this.Doppler[src-1]
	this.LkT[dst-1] = this.LkT[src-1]
	this.HalfAmb[dst-1] = this.HalfAmb[src-1]
	this.Cnr[dst-1] = this.Cnr[src-1]
	this.LLI[dst-1] = this.LLI[src-1]
}

func (this *GnssYObs) EmptySig(dst byte) {
	this.PhRngV[dst-1] = 0
	this.PsRngV[dst-1] = 0
	this.Doppler[dst-1] = 0
	this.LkT[dst-1] = 0
	this.HalfAmb[dst-1] = 0
	this.Cnr[dst-1] = 0
	this.LLI[dst-1] = 0
}

func (this *GnssYObs) CopyFrom(src *GnssYObs) {
	this.Satid = src.Satid
	this.NaviSys = src.NaviSys
	this.RoughR = src.RoughR
	for i := U8_0; i < 32; i++ {
		this.PsRngV[i] = src.PsRngV[i]
		this.PhRngV[i] = src.PhRngV[i]
		this.Doppler[i] = src.Doppler[i]
		this.LkT[i] = src.LkT[i]
		this.HalfAmb[i] = src.HalfAmb[i]
		this.Cnr[i] = src.Cnr[i]
		this.LLI[i] = src.LLI[i]
	}
}

func (this *GnssYObs) Reset() {
	this.Satid = 0
	this.NaviSys = 0
	this.RoughR = 0
	for i := U8_0; i < 32; i++ {
		this.PsRngV[i] = 0
		this.PhRngV[i] = 0
		this.Doppler[i] = 0
		this.LkT[i] = 0
		this.HalfAmb[i] = 0
		this.Cnr[i] = 0
		this.LLI[i] = 0
	}
}

/*
**

	YObsSigId2SigType 计算不完整
*/
func (this *GnssYObs) GetPhRngAsMeter(idx byte) float64 {
	sigtype := YObsSigId2SigType(this.NaviSys, idx+1)
	wl := GetWaveLength(this.NaviSys, sigtype, this.Satid)
	return this.PhRngV[idx] * wl
}

func (this *GnssYObs) ChangePhRng(sigId byte, srcwl, dstwl float64) {
	idx := sigId - 1
	if this.PhRngV[idx] == 0 {
		return
	}
	this.PhRngV[idx] = this.PhRngV[idx] * srcwl / dstwl
}

func (this *GnssYObs) IsSignalValidIdx(idx byte) bool {
	return this.PsRngV[idx] != 0 || this.PhRngV[idx] != 0
}

func (this *GnssYObs) IsValid() bool {
	rval := false
	for i := U8_0; i < 32; i++ {
		if this.IsSignalValidIdx(i) {
			rval = true
			break
		}
	}

	return rval
}

func (this *GnssYObs) GetPsRngString() string {
	var sb utils.BytesBuilder
	for i := U8_0; i < 32; i++ {
		if this.PsRngV[i] != 0 || this.PhRngV[i] != 0 {
			if sb.Len() > 0 {
				sb.AppendStr("\t")
			}
			sb.Appendf("%s:%.4f", YObsSigID2Code(this.NaviSys, i+1), this.PsRngV[i])
		}
	}
	return sb.String()
}

func (this *GnssYObs) SetSignal(sig *YObsSignal) {
	if sig.SigId == 0 {
		return
	}
	idx := sig.SigId - 1
	this.PsRngV[idx] = sig.PsV
	this.PhRngV[idx] = sig.PhV
	this.Doppler[idx] = sig.Doppler
	this.Cnr[idx] = sig.Cnr
	this.LkT[idx] = sig.LkT
	this.LLI[idx] = sig.LLI
	this.LkT[idx] = sig.LkT
	this.HalfAmb[idx] = sig.HalfAmb
}

func (this *GnssYObs) GetSingal(sigcode string) (rval *YObsSignal) {
	this.RangeSignalCopy(func(signal *YObsSignal) bool {
		if signal.GetSignalCode() == sigcode {
			rval = signal
		}
		return rval == nil
	})
	return
}

func (this *GnssYObs) GetSignalBySigID(sigId byte, signal *YObsSignal) {
	if sigId == 0 || sigId > 32 {
		return
	}
	idx := sigId - 1
	signal.NaviSys = this.NaviSys
	signal.SatId = this.Satid
	signal.SigId = sigId
	signal.PsV = this.PsRngV[idx]
	signal.PhV = this.PhRngV[idx]
	signal.Doppler = this.Doppler[idx]
	signal.Cnr = this.Cnr[idx]
}

func (this *GnssYObs) RangeSignal(fn func(signal *YObsSignal) bool) {
	var signal YObsSignal
	signal.NaviSys = this.NaviSys
	signal.SatId = this.Satid
	for i := U8_0; i < 32; i++ {
		if this.PsRngV[i] != 0 || this.PhRngV[i] != 0 {
			signal.Reset()
			signal.SigId = i + 1
			signal.PsV = this.PsRngV[i]
			signal.PhV = this.PhRngV[i]
			signal.Doppler = this.Doppler[i]
			signal.Cnr = this.Cnr[i]
			if !fn(&signal) {
				break
			}
		}
	}
}

func (this *GnssYObs) RangeSignalCopy(fn func(signal *YObsSignal) bool) {
	for i := U8_0; i < 32; i++ {
		if this.PsRngV[i] != 0 || this.PhRngV[i] != 0 {
			signal := &YObsSignal{}
			signal.NaviSys = this.NaviSys
			signal.SatId = this.Satid
			signal.SigId = i + 1
			signal.PsV = this.PsRngV[i]
			signal.PhV = this.PhRngV[i]
			signal.Doppler = this.Doppler[i]
			signal.Cnr = this.Cnr[i]
			if !fn(signal) {
				break
			}
		}
	}
}

func (this *GnssYObs) Write(bb *utils.BytesBuilder) {
	flag := 0
	for i := U8_0; i < 32; i++ {
		if this.PsRngV[i] != 0 || this.PhRngV[i] != 0 {
			if flag == 0 {
				bb.WriteString(GetPrnStrCode(this.Satid, this.NaviSys))
				bb.WriteString(" ")
				flag = 1
			}
			sigId := i + 1
			bb.WriteString(YObsSigID2Code(this.NaviSys, sigId))
			bb.Appendf("[%.2d] ", sigId)
			bb.WriteString(RinexFormatFloat(this.PsRngV[i]))
			bb.WriteString(RinexFormatFloat(this.PhRngV[i]))
			bb.WriteString(RinexFormatFloat(this.Doppler[i]))
			bb.WriteString(RinexFormatFloat(float64(this.Cnr[i])))
			bb.Appendf_PrefixFixed(5, " ", " %d  ", LockTime2Indicator(this.LkT[i]))
			bb.Appendf_PrefixFixed(5, " ", " %d  ", this.HalfAmb[i])

		}
	}

	if flag == 1 {
		bb.WriteString("\r\n")
	}
}
